package org.jaaksi.kottlindemo.generics

import android.app.Activity
import android.view.View
import org.jaaksi.kottlindemo.home.MainActivity

class TestKt {
    // 泛型类型参数约束:
    // 没有指定上界的类型形参将会使用 Any? 这个默认上界
    // 如何不允许null呢，使用<T:Any>来确保类型T是非空类型
    fun <T : Number> List<T>.sum(t: T): T { // : Number 表示上界
        return t
    }

    fun testOut() {
        // java中是不允许的，kotlin中List泛型声明是out的
        var list: List<Any> = listOf<String>()

    }

    // * 星投影
    fun test(data: List<*>) {
        val list = listOf(1, 2, 3)
        if (list is List<*>) {  // 星投影，类似Java的 <?>
        }
        // 使用 as 、 as? 进行转换
        data as? List<Int> ?: throw IllegalArgumentException("转换失败")
    }

    // 不懂
    inline fun <reified T> isA(value: Any) = value is T

    // 协变说明子类型化被保留了, 在Kotlin中，要声明类在某个类型参数上是协变的，在该类型参数的名称上添加 out 关键字；
    // 逆变是协变的镜像：对于逆变类，它的子类型化关系与用作类型实参的类的子类型化关系是相反的
    // fixme 协变：子类型化关系复制了它的类型实参的子类型化关系，逆变则反过来
    interface MyTranform<T> {
        fun tranform(t: T): T   // fixme 参数 t在in 位置，返回值 在out位置
    }

    interface SourceOut<out T /*: Number*/> {
        fun next(): T // out位置表示生产
    }

    interface SourceIn<in T> {
        fun test(t: T) // in位置表示消费
    }

    fun testOut(data: SourceOut<Number>?) {
        data?.next()
        val obj: SourceOut<Any>? = data
//    val obj2: SourceOut<Double>? = data // 错误
    }

    fun testIn(data: SourceIn<Number>?) {
        var obj: SourceIn<Double>? = data
//    var obj2: SourceIn<Any>? = data // 错误
        // in用于消费，Double是Number的子类，所以可以用来消费
        data?.test(1)

    }

    fun test1() {
        // public interface List<out E> List声明了out
        var list: List<String> = arrayListOf()
        var list2: List<Any> = list

        // Comparable类是逆形变
        //public interface Comparable<in T>
    }

    // ::format 的意思是将format方法作为参数
    fun pr(callback: (Int) -> String = ::format) {

    }

    fun format(value: Int): String {
        return value.toString()
    }
}



